package com.ww.exercise.coroutine.hard.q19

import kotlinx.coroutines.*
import java.util.concurrent.CompletableFuture
import java.util.concurrent.TimeUnit
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException

// 1.将CompletableFuture转换为suspend函数的工具方法
// TODO 继续跟一下fun lambda写法
suspend fun <T> CompletableFuture<T>.await(): T = suspendCancellableCoroutine { continuation ->
    // 完成时恢复协程
    whenComplete { result, error ->
        if (error != null) {
            continuation.resumeWithException(error)
        } else {
            continuation.resume(result)
        }
    }

    // 处理协程取消，映射到Future的cancel
    continuation.invokeOnCancellation {
        cancel(true)
    }
}

// 2.模拟第三方接口调用（保留原业务逻辑）
fun callThirdPartyApi(id: String): CompletableFuture<String> {
    // TODO 对于CompletableFuture API复习一下
    return CompletableFuture.supplyAsync {
        // 模拟网络延迟
        TimeUnit.MILLISECONDS.sleep(100)
        "ThirdPartyResponse($id)"
    }
}

// 3.模拟数据库操作（保留原业务逻辑）
fun saveToDatabase(data: String): CompletableFuture<Boolean> {
    return CompletableFuture.supplyAsync {
        TimeUnit.MILLISECONDS.sleep(50)
        true
    }
}

// 4.迁移后的业务流程 - 使用suspend函数
suspend fun processRequestCoroutine(id: String): Boolean = withContext(Dispatchers.IO) {
    // 调用第三方接口并等待结果
    val response = callThirdPartyApi(id).await()
    // 处理数据
    val processedData = "Processed($response)"
    // 保存到数据库并等待结果
    saveToDatabase(processedData).await()
}

// 5.验证代码 - 测试线程使用情况和吞吐量
fun main() = runBlocking {
    val requestCount = 10000
    val start = System.currentTimeMillis()

    // 使用协程并发处理多个请求
    val results = withContext(Dispatchers.IO) {
        (1..requestCount).map { id ->
            async {
                processRequestCoroutine(id.toString())
            }
        }.awaitAll()
    }

    val end = System.currentTimeMillis()
    val successCount = results.count { it }

    println("处理完成: ${requestCount}个请求，成功: ${successCount}个")
    println("耗时: ${end - start}ms")
    println("当前线程: ${Thread.currentThread().name}")
}